/****************************************************************************
 **
 ** This file is part of the yFiles extension package GraphML-3.2-yFiles-2.7.
 ** 
 ** yWorks proprietary/confidential. Use is subject to license terms.
 **
 ** Redistribution of this file or of an unauthorized byte-code version
 ** of this file is strictly forbidden.
 **
 ** Copyright (c) 2000-2009 by yWorks GmbH, Vor dem Kreuzberg 28, 
 ** 72070 Tuebingen, Germany. All rights reserved.
 **
 ***************************************************************************/

package demo.yext.graphml;

import java.awt.event.ActionEvent;
import java.io.IOException;
import java.io.File;
import java.net.URL;
import javax.swing.AbstractAction;
import javax.swing.Action;
import javax.swing.JFileChooser;
import javax.swing.JMenu;
import javax.swing.JMenuBar;
import javax.swing.filechooser.FileFilter;

import y.io.GMLIOHandler;
import y.io.IOHandler;
import y.io.YGFIOHandler;
import y.util.D;
import y.view.EditMode;
import y.view.Graph2D;
import y.view.hierarchy.HierarchyManager;
import yext.graphml.graph2D.GraphMLIOHandler;

/**
 * This demo allows to load and save graphs in the GraphML file format. 
 * Furthermore, it allows to load graphs in GML and YGF file format. 
 * A small list of predefined GraphML files can also be accessed from the menu. 
 */
public class GraphMLDemo extends ViewActionDemo
{
  HierarchyManager hierarchy;
  private GraphMLIOHandler ioHandler;

  private JFileChooser chooser;

  private File currentDir;

  /**
   * Creates a new instance of GraphMLDemo 
   */
  public GraphMLDemo()
  {
    //to enabled import of hierarchically nested and grouped graphs
    hierarchy = new HierarchyManager(view.getGraph2D());

    ioHandler = createGraphMLIOHandler();
    createChooser();
  }

  protected JMenuBar createMenuBar()
  {
    JMenuBar jtb = super.createMenuBar();
    JMenu sampleGraphMenu = createSampleGraphMenu();
    if(sampleGraphMenu != null) {
      jtb.add(sampleGraphMenu);
    }
    return jtb;
  }
  
  protected JMenu createSampleGraphMenu() {
    String[] resources = {
      "resources/ygraph/visual_features.graphml",
      "resources/ygraph/problemsolving.graphml",
      "resources/ygraph/funky.graphml",
      "resources/ygraph/simple.graphml",
      "resources/ygraph/grouping.graphml",
    };
    return createSampleGraphMenu(resources);
  }

  JMenu createSampleGraphMenu( final String[] resources ) {
    JMenu menu = new JMenu("Sample Graphs");
    int resolvedResourceCount = 0;
    for (int i = 0; i < resources.length; ++i) {
      final URL resource = getClass().getResource(resources[i]);
      if (resource != null) {
        ++resolvedResourceCount;
        menu.add(new LoadResourceAction(resource));
      } else {
        System.err.println("Could not resolve sample resource " + resources[i]);
      }
    }
    if (resolvedResourceCount > 0) {
      return menu;
    } else {
      return null;
    }
  }

  private void createChooser() {
    if (chooser == null) {
      chooser = new JFileChooser();

      chooser.addChoosableFileFilter(new FileFilter() {
        public boolean accept(final File f) {
          String s = f.getName().toLowerCase();
          return f.isDirectory() || s.endsWith(ioHandler.getFileNameExtension());
        }

        public String getDescription() {
          return ioHandler.getFileFormatString();
        }
      });
    }
  }

  protected GraphMLIOHandler createGraphMLIOHandler()
  {
    return new GraphMLIOHandler();
  }

  public GraphMLIOHandler getGraphMLIOHandler()
  {
    return ioHandler;
  }

  protected Action createLoadAction()
  {
    return new LoadAction();
  }

  protected Action createSaveAction()
  {
    return new SaveAction();
  }
  
  /**
   * Action that saves the current graph to a file in GraphML format.
   */
  class SaveAction extends AbstractAction
  {
    SaveAction()
    {
      super("Save...");
    }
    
    public void actionPerformed(ActionEvent e)
    {
      if(currentDir != null) {
        chooser.setCurrentDirectory(currentDir);
      }

      if(chooser.showSaveDialog(GraphMLDemo.this) == JFileChooser.APPROVE_OPTION)
      {
        String name = chooser.getSelectedFile().toString();
        currentDir = chooser.getCurrentDirectory();
        if (!name.endsWith(".graphml"))  {
          name = name + ".graphml";
        }
        IOHandler ioh = getGraphMLIOHandler();
        try
        {
          ioh.write(view.getGraph2D(),name);
        }
        catch (IOException ioe)
        {
            D.show(ioe);
        }
      }
    }
  }
 
 /**
   * Action that loads a graph from a specific file in GraphML format.
   */
  class LoadResourceAction extends AbstractAction
  {
    URL resource;
    LoadResourceAction(URL resource)
    {
      putValue(AbstractAction.NAME,  urlToName(resource));
      this.resource = resource;
    }
    
    String urlToName(URL url)
    {
      String file = url.getFile();
      return file.substring(file.lastIndexOf('/')+1);
    }
      
    public void actionPerformed(ActionEvent ev)
    {
      try
      {
        Graph2D graph = view.getGraph2D();
        graph.clear();
        IOHandler ioh = getGraphMLIOHandler();
        ioh.read(graph, resource);
        view.fitContent();
        graph.updateViews();
      }
      catch (IOException ioe)
      {
        D.show(ioe);
      }
    }
  }

  /**
   * Action that loads the current graph from a file in GraphML, YGF or GML format.
   */
  class LoadAction extends AbstractAction
  {
    LoadAction()
    {
      super("Load...");
    }
    
    public void actionPerformed(ActionEvent e)
    {
      if(currentDir != null) {
        chooser.setCurrentDirectory(currentDir);
      }
      if(chooser.showOpenDialog(GraphMLDemo.this) == JFileChooser.APPROVE_OPTION)
      {
        String name = chooser.getSelectedFile().toString();
        currentDir = chooser.getCurrentDirectory();
        IOHandler ioh = null;
        if (name.endsWith(".gml")) {
          ioh = new GMLIOHandler();
        }
        else if(name.endsWith(".ygf"))
        {
          ioh = new YGFIOHandler();
        }
        else //default is GraphML
        {
          if (!name.endsWith(".graphml")) {
            name += ".graphml";
          }
          ioh = getGraphMLIOHandler();
        }
      
        try
        {
          Graph2D graph = view.getGraph2D();
          graph.clear();
          ioh.read(graph, name);
          view.fitContent();
          graph.updateViews();
        }
        catch (IOException ioe)
        {
          D.show(ioe);
        }
      }
    }
  }

  /**
   * Launches this demo.
   */
  public static void main(String[] args)
  {
    initLnF();
    final GraphMLDemo demo = new GraphMLDemo();
    demo.start();
  }
}
